//============================================================================
// Name        : TCPSocket.cpp
// Author      : O.M.A.V.
// Description : De implementation file van de TCPSocket class
//============================================================================

#include "TCPSocket.h"

/*
* Create a new TCPSocket.
*
* portNumber:		TCP port to listen on.
* QueueLength:		Maximum amount of simultaneous connections.
*/
TCPSocket::TCPSocket(unsigned short int portNumber, int queueLength)
{
	// Maak nieuwe socket
	sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

	// Socket maken niet gelukt
	if(sock < 0)
	{
		throwError("Kan de socket niet maken.");
	}
	// Socket maken wel gelukt
	else
	{
		// Bind socket
		bindSocket(portNumber);

		// Begin met luisteren naar binnenkomende verbindingen
		listen(queueLength);
	}
}

/*
 * Create a new TCPSocket.
 *
 * sock:	socket die gebruikt moet worden om de TCPSocket te maken
 */
TCPSocket::TCPSocket(int sock)
{
	this->sock = sock;
}

/*
 * Bind socket aan IP-adres en poort nummer
 *
 * portNr:		poortnummer waar naar geluisterd moet worden
 */
void TCPSocket::bindSocket(unsigned short int portNr)
{
	// Get the local IP address
	in_addr_t localIP = HostInfo::GetLocalIPAddress("eth0");

	// Collect binding information
	sockaddr_in localInfo;
	localInfo.sin_family = AF_INET;
	localInfo.sin_addr.s_addr = localIP;
	localInfo.sin_port = htons(portNr);

	// Bind socket
	int error = bind(sock, (sockaddr *) &localInfo, sizeof(sockaddr_in));

	// Check for errors
	if (error < 0)
	{
		throwError("Kan de poort niet binden aan het IP adres.");
	}
}

/*
 * Begin met luisteren naar binnen komende verbindigen
 *
 * queueLength:		Maximale lengte van de wachtrij
 */
void TCPSocket::listen(int queueLength)
{
	// Begin met luisteren naar binnenkomende verbindingen
	int error = ::listen(sock, queueLength);

	// Check error
	if (error < 0)
	{
		throwError("Fout bij het luisteren naar een poort");
	}
}

/*
 * Toon error en sluit applicatie
 *
 * msg:		bericht dat bij de error moet worden getoond
 */
void TCPSocket::throwError(const char msg[]) const
{
	// Toon foutmelding
	perror(msg);

	// Sluit applicatie
	exit(1);
}

/*
 * Accepteer nieuwe verbindingsb
 *
 * Return: 	TCPSocket van de geaccepteerde verbinding
 */
TCPSocket *TCPSocket::accept()
{
	// Accepteer nieuwe verbinding
	int newSock = ::accept(sock, NULL, 0);

	// Check error
	if (newSock < 0)
	{
		throwError("Fout bij het accepteren van een nieuwe verbinding");
	}

	// Retun TCPsocket van de verbonden client
	return new TCPSocket(newSock);
}

/*
 * Verstuur bericht naar client
 *
 * msg:		Het bericht wat verstuurd moet worden
 *
 */
void TCPSocket::send(const char *msg)
{
	// Verstuur bericht naar client
	int error = ::send(sock, msg, strlen(msg), 0);

	// Check voor errors
	if(error < 0)
	{
		throwError("Fout bij het versturen!");
	}
}

/*
 * Ontvang bericht van client
 *
 * buffer:		 Buffer waarin het ontvangen bericht moet worden opgeslagen
 * bufferLength: Maximale grote van de buffer
 *
 * return:	waarde die status van het ontvangen aangeeft
 */
int TCPSocket::recv(char *buffer, int bufferLength)
{
	// Ontvang bericht
	int recv = ::recv(sock, buffer, bufferLength, 0);

	// Check error
	if (recv < 0)
	{
		perror("Fout bij het ontvangen!");
	}

	return recv;
}
